package spring.data.jpa.repository;

import java.util.List;
import java.util.Map;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public interface CommonJpaRepository<T, D> extends JpaRepository<T, D>, JpaSpecificationExecutor<T>, SQLExecutor {

    public Class<T> getJavaType();

    /**
     * 获取指定条数的数据
     * 
     * @param spec
     *            查询条件
     * @param sort
     *            排序
     * @param size
     *            返回大小
     * @return
     */
    public List<T> findOrderTop(Specification<T> spec, Sort sort, int size);

    public List<T> findTop(Specification<T> spec, int size);

    public List<T> findOrderTop(Sort sort, int size);

    public List<T> findTop(int size);

    /**
     * 获取指定对象类型的任一对象
     * 
     * @param clazz
     *            对象类型
     * @param id
     *            对象ID
     * @return
     */
    public <X, O> X findOne(Class<X> clazz, O id);

    /**
     * 根据某些条件查询某个对象
     * 
     * @param clazz
     *            对象类型
     * @param spec
     *            条件
     * @return
     */
    public <X> X findOne(Class<X> clazz, Specification<X> spec);

    /**
     * 保存指定类型的任一对象
     * 
     * @param clazz
     *            对象类型
     * @param entity
     *            要保存的对象
     * @return
     */
    public <X> X save(Class<X> clazz, X entity);

    /**
     * 删除指定对象类型的一个对象
     * 
     * @param clazz
     *            对象类型
     * @param id
     *            对象ID
     */
    public <X, O> void remove(Class<X> clazz, O id);

    /**
     * 查询指定对象类型的所有对象
     * 
     * @param clazz
     *            对象类型
     * @return 符合查询的对象集合
     */
    public <X> List<X> findAll(Class<X> clazz);

    /**
     * 查询指定类型的所有对象,按sort排序
     * 
     * @param clazz
     *            对象类型
     * @param sort
     *            排序对象
     * @return 符合查询的对象集合
     */
    public <X> List<X> findAll(Class<X> clazz, Sort sort);

    /**
     * 查询指定类型的所有对象
     * 
     * @param clazz
     *            对象类型
     * @param spec
     *            查询条件
     * @return 扶额和查询的对象集合
     */
    public <X> List<X> findAll(Class<X> clazz, Specification<X> spec);

    /**
     * 按分页查询指定对象的集合
     * 
     * @param clazz
     *            对象类型
     * @param spec
     *            查询条件
     * @param pageable
     *            分页对象
     * @return 符合查询的分页对象集合Page
     */
    public <X> Page<X> findPage(Class<X> clazz, Specification<X> spec, Pageable pageable);

    /**
     * 查询指定类型的对象集合,可排序
     * 
     * @param clazz
     *            对象类型
     * @param spec
     *            查询条件
     * @param sort
     *            排序对象
     * @return 符合查询的对象集合
     */
    public <X> List<X> findAll(Class<X> clazz, Specification<X> spec, Sort sort);

    /**
     * 按jpql查询所有对象,参数从 0 开始依次绑定
     * 
     * @param jpql
     *            jpql语句
     * @param values
     *            过滤条件
     * @return 符合查询语句的所有对象集合
     */
    public <X> List<X> findAll(String jpql, Object... values);

    /**
     * 按jpql查询所有对象,参数按名称绑定
     * 
     * @param jpql
     *            jpql语句
     * @param values
     *            绑定的参数
     * @return 扶额和查询语句的所有对象集合
     */
    public <X> List<X> findAll(String jpql, Map<String, Object> values);

    /**
     * 根据jpql查询对象的分页,注意,此处的pageable不指定Sort对象,要排序直接在jpql语句中写
     * 
     * @param jpql
     *            jpql语句,eg:select u from User u where u.name=?0 and u.pwd=?1
     * @param pageable
     *            分页对象
     * @param values
     *            jpql参数,从 0 开始绑定
     * @return 符合查询的分页对象
     */
    public <X> Page<X> findPage(String jpql, Pageable pageable, Object... values);

    /**
     * 根据jpql查询对象的分页,注意,此处的pageable不指定Sort对象,要排序直接在jpql语句中写
     * 
     * @param jpql
     *            jpql语句 ,eg:select u from User u where u.name=:uname and
     *            u.pwd=:pwd
     * @param pageable
     *            分页对象
     * @param values
     *            jpql参数,按名称绑定
     * @return 符合查询的分页对象
     */
    public <X> Page<X> findPage(String jpql, Pageable pageable, Map<String, Object> values);

    /**
     * 执行更新或删除语句
     * 
     * @param jpql
     *            jpql语句
     * @param values
     *            参数,从0 开始依次绑定
     * @return
     */
    public int execute(String jpql, Object... values);

    /**
     * 执行更新或删除语句
     * 
     * @param jpql
     *            jpql语句
     * @param values
     *            参数,按名称绑定
     * @return
     */
    public int execute(String jpql, Map<String, Object> values);

}
